home *** CD-ROM | disk | FTP | other *** search
- /* GRAPHIC LISP */
- /* Scritto nel 1991-94 da Zoia Andrea Michele */
- /* Via Pergola #1 Tirano (SO) Tel. 0342-704210 */
- /* file clos_cl1.c */
-
- #include "clos.h"
-
-
- node AccessorList;
- node ThisClass;
- node ThisSupers;
- node ThisInitargs;
-
-
- node defclass_alloclist();
- void defclass_chk_supers();
- void defclass_parse_def();
- int defclass_parse_initform();
- int defclass_parse_initarg();
- void defclass_mkaccessor();
- void defclass_chk_initarg();
-
-
- /* ( DEFCLASS nome (supers)
- (
- (nome :accessor nome :initform nome :initarg nome)
- (................................................)
- )
- )
- */
- void lf_defclass LF_PARAMS
- {
- /* CLASS_TYPE--> ( (superclasses) (initforms) (initargs) ) */
-
- node supers;
- node initforms=NIL;
- node initargs=NIL;
- node prev_initforms;
- node prev_initargs;
- node ni=nin;
- lsiz_t index;
-
- if(IS_CONS(nin)){
- eval(CONSLEFT(nin),nout,genv,lenv,EVAL_SETF);
- if(nout->type==P_VALUE || nout->type==P_UNBOUNDVALUE ||
- nout->type==P_CLASS || nout->type==P_UNBOUNDCLASS )
- {
- if(HAS_CLASS(nout->node)){
- error(E_CLASSREDEF,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&nout->node);
- }
- ThisClass=nout->node;
- if(IS_CONS(nin=CONSRIGHT(nin))){
- supers=list_dup(CONSLEFT(nin),DUP_LASTNIL);
- if(!IS_CONS(supers)){
- /* se non si specificano superclassi allora si mette */
- /* solo T ,invece se si specificano superclassi */
- /* sono solo queste che vanno nella supers-list */
- TYPE(supers=node_make())|=NT_IS_CONS;
- CONSLEFT(supers)=T;
- CONSRIGHT(supers)=NIL;
- }else{
- /* controlla la lista supers e vede se e' composta solo di nomi */
- defclass_chk_supers(supers);
- }
- ThisSupers=supers;
- index=1; /* conta il numero del campo */
- AccessorList=NIL; /* inizializza AccessorList */
- nin=CONSLEFT(CONSRIGHT(nin));
- while(IS_CONS(nin)){
- if(initforms==NIL){
- initforms=prev_initforms=node_make();
- ThisInitargs=initargs =prev_initargs =node_make();
- }else{
- CONSRIGHT(prev_initforms)=node_make();
- CONSRIGHT(prev_initargs )=node_make();
- prev_initforms=CONSRIGHT(prev_initforms);
- prev_initargs =CONSRIGHT(prev_initargs );
- }
- TYPE(prev_initforms)|=NT_IS_CONS;
- TYPE(prev_initargs)|=NT_IS_CONS;
- CONSLEFT(prev_initforms)=CONSRIGHT(prev_initforms)=
- CONSLEFT(prev_initargs )=CONSRIGHT(prev_initargs )=NIL;
- /* scorre le definizioni */
- defclass_parse_def(CONSLEFT(nin),&CONSLEFT(prev_initforms),&CONSLEFT(prev_initargs),index++);
- nin=CONSRIGHT(nin);
- }
- /* alloca una lista di 3 elementi */
- /* ( supers initforms initargs ) */
- CLASS(nout->node)=defclass_alloclist(supers,initforms,initargs);
- TYPE(nout->node)|=NT_HAS_CLASS;
- nout->type=P_CLASS;
- /* valida tutti gli accessor */
- while(AccessorList!=NIL){
- ni=CONSLEFT(AccessorList);
- TYPE(ni)|=NT_HAS_FUNCTION;
- AccessorList=CONSRIGHT(AccessorList);
- }
- return;
- }
- error(E_FEWARGS,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&ni);
- }
- ni=calc_pointer(nout);
- error(E_BADARGS,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&ni);
- }
- error(E_FEWARGS,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&nin);
- }
-
-
- node defclass_alloclist(supers,initforms,initargs)
- node supers;
- node initforms;
- node initargs;
- {
- node ret=node_make();
-
- CONSRIGHT(ret)=node_make();
- CONSLEFT(ret)=supers;
- CONSRIGHT(CONSRIGHT(ret))=node_make();
- CONSLEFT(CONSRIGHT(ret))=initforms;
- CONSLEFT(CONSRIGHT(CONSRIGHT(ret)))=initargs;
- CONSRIGHT(CONSRIGHT(CONSRIGHT(ret)))=NIL;
-
- TYPE(ret)=
- TYPE(CONSRIGHT(ret))=
- TYPE(CONSRIGHT(CONSRIGHT(ret)))|=NT_IS_CONS;
-
- return ret;
- }
-
- void defclass_chk_supers(supers)
- node supers;
- {
- node tmp;
- node s=supers;
- while(IS_CONS(supers)){
- if(IS_NAME(CONSLEFT(supers))&&HAS_NAME(CONSLEFT(supers))){
- if(HAS_CLASS(CONSLEFT(supers))){
- /* ok CONSLEFT(supers) e' un nome di classe */
- /* si controlla se appare precedentemente nella lista supers */
- tmp=s;
- while(tmp!=supers){
- if(CONSLEFT(supers)==CONSLEFT(tmp))
- error(E_SUPERDUP,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&CONSLEFT(supers));
- tmp=CONSRIGHT(tmp);
- }
- supers=CONSRIGHT(supers);
- continue;
- }
- error(E_UNBOUNDCLASS,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&CONSLEFT(supers));
- }
- error(E_BADARGS,ERR_MERROR|ERR_TBLVL|ERR_PNODE,&CONSLEFT(supers));
- }
- }
-
-
- void defclass_parse_def(def,initf,inita,index)
- node def;
- node *initf;
- node *inita;
- lsiz_t index;
- {
- node aux;
- node nerr=def;
- node accessor=node_alloc("ACCESSOR");
-
- /*
- def= ( {name}?
- :accessor accessor-procname
- {:initform initform-sx }?
- {:initarg { intargs-name | initargs_cname | initargs-ename }}?
- )
- */
- if(IS_CONS(def)){
- /* il nome e' totalmente inutile */
- /* se c'e' lo si salta se non c'e' si passa oltre */
- aux=CONSLEFT(def);
- if(IS_NAME(aux)&&HAS_NAME(aux)){
- if(IS_CONS(def=CONSRIGHT(def))){
- aux=CONSLEFT(def);
- }
- }
- /* ora aux deve contenere :ACCESSOR */
- if(IS_VALUE(aux) && GET_VTYPE(aux)==NT_CNAME && CNAME(aux)==accessor){
- if(IS_CONS(def=CONSRIGHT(def))){
- aux=CONSLEFT(def);
- /* aux deve contenere il nome dell' accessor */
- if(IS_NAME(aux)&&HAS_NAME(aux)){
- /* ora aux e' OK e gli si collega l'accessor */
- defclass_mkaccessor(aux,index);
- /* ora si controlla se ci sono nell' ordine: :INITFORM e :INITARG */
- if(IS_CONS(def=CONSRIGHT(def))){
- /* c'e' ancora qualcosa e def contiene il resto della lista */
- if(defclass_parse_initform(def,initf)){
- /* non e' :INITFORM */
- if(defclass_parse_initarg(def,inita)){
- /* non e' :INITARG */
- error(E_DEFCLASSYNTAX,ERR_MERROR|ERR_PVOID|ERR_TBLVL,&nerr);
- }
- /* e' :INITARG allora si ritorna */
- /* inserendo NIL nella initf */
- *initf=NIL;
- return;
- }
- /* e' initform */
- def=CONSRIGHT(CONSRIGHT(def));
- /* def contiene il resto della lista */
- if(IS_CONS(def)){
- /* c'e' ancora qualcosa e puo' essere solo :INITARG */
- if(defclass_parse_initarg(def,inita))
- /* non e' initarg: errore */
- error(E_DEFCLASSYNTAX,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&nerr);
- return;
- }
- /* c'e' solo initform si mette NIL in inita */
- *inita=NIL;
- return;
- }
- /* non ci sono ne initform ne initarg si mette NIL nella inta e intf*/
- *inita=NIL;
- *initf=NIL;
- return;
- }
- /* l'accessor aux non e' un nome */
- error(E_BADARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&aux);
- }
- error(E_FEWARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&nerr);
- }
- error(E_BADARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&aux);
- }
- error(E_FEWARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&nerr);
- }
-
-
- int defclass_parse_initform(def,initf)
- node def;
- node *initf;
- {
- /* def e' sicuramente un CONS */
- /* si controlla se e' (:INITFORM sx) */
-
- node initform=node_alloc("INITFORM");
- node aux;
- node l;
-
- aux=CONSLEFT(def);
- if(IS_VALUE(aux)&&GET_VTYPE(aux)==NT_CNAME&&CNAME(aux)==initform){
- if(IS_CONS(def=CONSRIGHT(def))){
- if(IS_CONS(CONSLEFT(def))){
- l=list_dup(CONSLEFT(def),DUP_LASTNIL);
- }else{
- l=CONSLEFT(def);
- }
- *initf=l;
- return OK;
- }
- error(E_FEWARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&def);
- }
- return ERROR;
- }
-
- int defclass_parse_initarg(def,inita)
- node def;
- node *inita;
- {
- /* def e' sicuramente un CONS */
- /* si controlla se e' (:INITARG sx) */
- /* sx deve essere un nome!=da NIL */
- /* oppure in :nome o &nome */
-
- node initarg=node_alloc("INITARG");
- node aux;
-
- aux=CONSLEFT(def);
- if(IS_VALUE(aux)&&GET_VTYPE(aux)==NT_CNAME&&CNAME(aux)==initarg){
- if(IS_CONS(def=CONSRIGHT(def))){
- aux=CONSLEFT(def);
- if(aux==NIL)
- error(E_BADARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&NIL);
- if( IS_NAME(aux) && HAS_NAME(aux) ){
- defclass_chk_initarg(aux);
- *inita=aux;
- return OK;
- }
- if( IS_VALUE(aux) &&
- ((GET_VTYPE(aux)==NT_CNAME) || (GET_VTYPE(aux)==NT_ENAME)) ){
- defclass_chk_initarg(aux);
- *inita=aux;
- return OK;
- }
- error(E_BADARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&aux);
- }
- error(E_FEWARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&def);
- }
- return ERROR;
- }
-
-
- void defclass_mkaccessor(aux,index)
- node aux;
- lsiz_t index;
- {
- /* aux e' un nome */
- /* controlla che l'accessor non sia gia' stato definito */
- /* se e' cosi' lo alloca ma */
- /* non marca il tipo di aux cosi' se c'e' un errore l'accessor */
- /* viene liberato */
- /* alla fine si marcano comunque tutti gli accessor che finiscono in una */
- /* lista */
-
- node n;
-
- /* aux e' un nome ma si controlla se non ha gia' un accessor */
- /* collegato in modo da trovare errori di duplicazione */
- /* di nomi di accessori di struttura */
- if(HAS_FUNCTION(aux)&&IS_VALUE(FUNCTION(aux))&&
- (GET_VTYPE(FUNCTION(aux))==NT_ACCESSOR))
- error(E_ACCESSORREDEF,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&aux);
-
- /* si controlla ovviamente che non sia anche in AccessorList */
- n=AccessorList;
- while(n!=NIL){
- if(CONSLEFT(n)==aux)
- error(E_ACCESSORREDEF,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&aux);
- n=CONSRIGHT(n);
- }
-
- /* si alloca l'accessor */
- TYPE(n=node_make())|=NT_IS_VALUE+NT_ACCESSOR;
- ACCESSOR_NAME(n)=ThisClass;
- ACCESSOR_FIELD(n)=index;
-
- FUNCTION(aux)=n;
-
- TYPE(n=node_make())|=NT_IS_CONS;
- CONSLEFT(n)=aux;
- CONSRIGHT(n)=AccessorList;
- AccessorList=n;
-
- }
-
-
-
- void defclass_chk_initarg(inita)
- node inita;
- {
- node s=ThisSupers;
- node cs;
- node c;
-
-
- /* controlla le duplicazioni degli initarg nelle superclassi */
- /* s e' una lista di nomi con classe */
- while(IS_CONS(s)){
- cs=CONSLEFT(s);
- if(cs==T){ /* salta T */
- s=CONSRIGHT(s);
- continue;
- }
- cs=CONSLEFT(CONSRIGHT(CONSRIGHT(CLASS(cs))));
- /* cs=lista di initargs della superclasse s */
- while(IS_CONS(cs)){
- c=CONSLEFT(cs);
- if(IS_VALUE(inita)&&IS_VALUE(c)){
- if(GET_VTYPE(inita)==GET_VTYPE(c)){
- /* tutti e 2 cname o ename */
- if(NODE(inita)==NODE(c))
- error(E_INITARGREDEF,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&inita);
- }
- }else{
- /* allora sono tutti e 2 dei nomi */
- if(c==inita)
- error(E_INITARGREDEF,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&inita);
- }
- cs=CONSRIGHT(cs);
- }
- s=CONSRIGHT(s);
- }
-
- /* si controllano anche le duplicazioni 'locali' */
- /* cs=lista di initargs della superclasse s */
- cs=ThisInitargs;
- while(IS_CONS(cs)){
- c=CONSLEFT(cs);
- if(IS_VALUE(inita)&&IS_VALUE(c)){
- if(GET_VTYPE(inita)==GET_VTYPE(c)){
- /* tutti e 2 cname o ename */
- if(NODE(inita)==NODE(c))
- error(E_INITARGREDEF,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&inita);
- }
- }else{
- /* allora sono tutti e 2 dei nomi */
- if(c==inita)
- error(E_INITARGREDEF,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&inita);
- }
- cs=CONSRIGHT(cs);
- }
- }
-
-